<html>
<script>
// http://www.cnblogs.com/xxcanghai/p/4991870.html

/*
Jerry: 2016-01-28 14:06PM
最内层的return出去的fun函数不是第二层fun函数，是最外层的fun函数。

所以，三个fun函数的关系也理清楚了，第一个等于第三个，他们都不等于第二个
*/
function fun(n,o) {
  console.log(o)
  return {
    fun:function(m){
      return fun(m,n);
    }
  };
}
var a = fun(0); // undefined n为0，但是o没有赋值，因此为undefined
// 返回一个新的fun, 接受一个新的参数m，然后调用自己，此时传入的m为1，但是n仍然为闭包的值，即0
// a.fun(1);  // 0
// a.fun(2);  // 0
// a.fun(3);  // 0 Jerry 2016-01-27 17:34PM 如果a = fun(0)改成2，连续输出3个2. 

var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?var c = fun(0).fun(1);  c.fun(2);  c.fun(3);//undefined,?,?,?//问:三行a,b,c的输出分别是什么？
/*
先从fun(0)开始看，肯定是调用的第一层fun函数；而他的返回值是一个对象，所以第二个fun(1)调用的是第二层fun函数，后面几个也是调用的第二层fun函数。

遂：

在第一次调用第一层fun(0)时，o为undefined；

第二次调用 .fun(1)时m为1，此时fun闭包了外层函数的n，也就是第一次调用的n=0，即m=1，n=0，并在内部调用第一层fun函数fun(1,0);所以o为0；

第三次调用 .fun(2)时m为2，此时当前的fun函数不是第一次执行的返回对象，而是第二次执行的返回对象。而在第二次执行第一层fun函数时时(1,0)所以n=1,o=0,返回时闭包了第二次的n，遂在第三次调用第三层fun函数时m=2,n=1，即调用第一层fun函数fun(2,1)，所以o为1；

第四次调用 .fun(3)时m为3，闭包了第三次调用的n，同理，最终调用第一层fun函数为fun(3,2)；所以o为2；

即最终答案：undefined,0,1,2
*/

function fn() {
  var num = 0;
  return function() {
    console.log(num++);
  }
}

var a = fn();
a();  // 0
a();  // 1
var b = fn();
b();  // 0
b();  // 1

/*
fun(0)为执行第一层fun函数，.fun(1)执行的是fun(0)返回的第二层fun函数，这里语句结束，遂c存放的是fun(1)的返回值，而不是fun(0)的返回值，所以c中闭包的也是fun(1)第二次执行的n的值。c.fun(2)执行的是fun(1)返回的第二层fun函数，c.fun(3)执行的也是fun(1)返回的第二层fun函数。

遂：

在第一次调用第一层fun(0)时，o为undefined；

第二次调用 .fun(1)时m为1，此时fun闭包了外层函数的n，也就是第一次调用的n=0，即m=1，n=0，并在内部调用第一层fun函数fun(1,0);所以o为0；

第三次调用 .fun(2)时m为2，此时fun闭包的是第二次调用的n=1，即m=2，n=1，并在内部调用第一层fun函数fun(2,1);所以o为1；

第四次.fun(3)时同理，但依然是调用的第二次的返回值，遂最终调用第一层fun函数fun(3,1)，所以o还为1

即最终答案：undefined,0,1,1
*/
var c = fun(0).fun(1);
c.fun(2);  
c.fun(3);

/*
创建一个变量，内容为一个带有名称的函数

var fn1=function xxcanghai(){};
注意：具名函数表达式的函数名只能在创建函数内部使用

即采用此种方法创建的函数在函数外层只能使用fn1不能使用xxcanghai的函数名。xxcanghai的命名只能在创建的函数内部使用

原因也非常简单，因为函数作用域链的问题，采用var的是在外部创建了一个fn变量，函数内部当然可以在内部寻找不到fn后向上册作用域查找fn，而在创建对象内部时，因为没有在函数作用域内创建fn，所以无法访问。

*/
</script>
</html>